package com.enjoy.mediademo;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.Arrays;

// 主活动类，继承自 AppCompatActivity，用于实现相机录制功能
public class AndroidCameraActivity extends AppCompatActivity {
    // 日志标签，方便调试时输出信息
    private static final String TAG = AndroidCameraActivity.class.getSimpleName();
    // 请求相机权限的请求码
    private static final int REQUEST_CAMERA_PERMISSION = 200;
    // 相机设备对象，用于控制相机
    private CameraDevice cameraDevice;
    // 媒体录制器对象，用于录制音频和视频
    private MediaRecorder mediaRecorder;
    // 纹理视图，用于显示相机预览画面
    private TextureView textureView;
    // 录制按钮，用于控制录制的开始和停止
    private Button recordButton;
    // 标记是否正在录制
    private boolean isRecording = false;
    // 相机 ID，用于标识要使用的相机
    private String cameraId;
    // 后台处理程序，用于在后台线程执行任务
    private Handler backgroundHandler;
    // 后台线程，用于处理相机操作，避免阻塞主线程
    private HandlerThread backgroundThread;

    private Handler upviewHandler;

    // 此注解用于抑制 findViewById 可能出现的类型转换警告
    @SuppressLint("WrongViewCast")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 设置当前活动的布局文件
        setContentView(R.layout.activity_camera);
        // 请求所需的权限，如相机、录音和存储权限
        requestPermissions();
        // 通过 ID 找到纹理视图
        textureView = findViewById(R.id.surfaceView);
        // 通过 ID 找到录制按钮
        recordButton = findViewById(R.id.recordButton);

        // 为录制按钮设置点击监听器
        recordButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isRecording) {
                    // 如果正在录制，则停止录制
                    stopRecording();
                } else {
                    // 如果未录制，则开始录制
                    startRecording();
                }
            }
        });

        upviewHandler=new UpviewHandler(this);
    }

    // 请求相机、录音和存储权限的方法
    private void requestPermissions() {
        // 检查相机权限是否已授予
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                != PackageManager.PERMISSION_GRANTED ||
                // 检查录音权限是否已授予
                ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO)
                        != PackageManager.PERMISSION_GRANTED ||
                // 检查存储权限是否已授予
                ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                        != PackageManager.PERMISSION_GRANTED) {
            // 如果有任何权限未授予，则请求这些权限
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.CAMERA,
                            Manifest.permission.RECORD_AUDIO,
                            Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    REQUEST_CAMERA_PERMISSION);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        // 启动后台线程，用于处理相机操作
        startBackgroundThread();
        if (textureView.isAvailable()) {
            // 如果纹理视图可用，则打开相机
            openCamera();
        } else {
            // 如果纹理视图不可用，则设置纹理视图的监听器
            textureView.setSurfaceTextureListener(textureListener);
        }
    }

    @Override
    protected void onPause() {
        // 停止后台线程
        stopBackgroundThread();
        super.onPause();
    }

    // 纹理视图的监听器，用于监听纹理视图的状态变化
    private final TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            // 当纹理视图可用时，打开相机
            openCamera();
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
            // 处理纹理视图大小变化，这里暂时为空
        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
            return true;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surface) {
            // 处理纹理视图更新，这里暂时为空
        }
    };

    // 相机设备的状态回调，用于监听相机设备的状态变化
    private final CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            // 当相机设备打开时，记录日志并保存相机设备对象
            Log.e(TAG, "onOpened: ");
            cameraDevice = camera;
            if (!isRecording) {
                // 如果未在录制，则创建相机预览
                createCameraPreview();
            }
        }

        @Override
        public void onDisconnected(@NonNull CameraDevice camera) {
            // 当相机设备断开连接时，记录日志并关闭相机设备
            Log.e(TAG, "onDisconnected: ");
            camera.close();
            cameraDevice = null;
        }

        @Override
        public void onError(@NonNull CameraDevice camera, int error) {
            // 当相机设备出现错误时，记录错误日志并关闭相机设备
            Log.e(TAG, "onError: error" + error);
            camera.close();
            cameraDevice = null;
        }
    };

    // 打开相机的方法
    private void openCamera() {
        // 获取相机管理器对象
        CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                // 如果系统版本在 Android 5.0 及以上，获取相机 ID，这里固定选择索引为 3 的相机
                cameraId = manager.getCameraIdList()[3];
                Log.e(TAG, "openCamera: cameraId"+cameraId);
            }
            // 获取相机的特性信息
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                // 如果相机权限未授予，则请求相机和录音权限
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO}, REQUEST_CAMERA_PERMISSION);
                return;
            }
            // 打开指定 ID 的相机，并传入状态回调和后台处理程序
            manager.openCamera(cameraId, stateCallback, backgroundHandler);
        } catch (CameraAccessException e) {
            // 捕获相机访问异常并打印堆栈信息
            e.printStackTrace();
        }
    }

    // 创建相机预览的方法
    private void createCameraPreview() {
        try {
            // 获取纹理视图的纹理对象
            SurfaceTexture texture = textureView.getSurfaceTexture();
            // 设置纹理的默认缓冲区大小
            texture.setDefaultBufferSize(textureView.getWidth(), textureView.getHeight());
            // 根据纹理对象创建 Surface 对象
            Surface surface = new Surface(texture);

            // 创建预览请求构建器，使用预览模板
            CaptureRequest.Builder previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            // 将 Surface 对象添加到预览请求的目标中
            previewRequestBuilder.addTarget(surface);

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                // 如果系统版本在 Android 5.0 及以上，创建相机捕获会话
                cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
                    @Override
                    public void onConfigured(@NonNull CameraCaptureSession session) {
                        if (cameraDevice == null) return;
                        try {
                            // 构建预览请求
                            CaptureRequest previewRequest = previewRequestBuilder.build();
                            // 设置重复请求，开始预览
                            session.setRepeatingRequest(previewRequest, null, backgroundHandler);
                        } catch (CameraAccessException e) {
                            // 捕获相机访问异常并打印堆栈信息
                            e.printStackTrace();
                        }
                    }

                    @Override
                    public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                        // 当会话配置失败时，显示提示信息
                        Toast.makeText(AndroidCameraActivity.this, "Configuration change", Toast.LENGTH_SHORT).show();
                    }
                }, null);
            }
        } catch (CameraAccessException e) {
            // 捕获相机访问异常并打印堆栈信息
            e.printStackTrace();
        }
    }

    // 开始录制的方法，要求系统版本在 Android 5.0 及以上
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void startRecording() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED ||
                ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            // 如果录音或相机权限未授予，则请求这些权限
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSION);
            return;
        }
        try {
            // 设置媒体录制器
            setUpMediaRecorder();
            // 获取纹理视图的纹理对象
            SurfaceTexture texture = textureView.getSurfaceTexture();
            // 设置纹理的默认缓冲区大小
            texture.setDefaultBufferSize(textureView.getWidth(), textureView.getHeight());
            // 根据纹理对象创建预览 Surface 对象
            Surface previewSurface = new Surface(texture);
            // 获取媒体录制器的 Surface 对象
            Surface recorderSurface = mediaRecorder.getSurface();

            // 创建录制请求构建器，使用录制模板
            CaptureRequest.Builder previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
            // 将预览 Surface 对象添加到请求目标中
            previewRequestBuilder.addTarget(previewSurface);
            // 将录制 Surface 对象添加到请求目标中
            previewRequestBuilder.addTarget(recorderSurface);

            // 创建相机捕获会话，包含预览和录制的 Surface 对象
            cameraDevice.createCaptureSession(Arrays.asList(previewSurface, recorderSurface), new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {
                    try {
                        // 构建录制请求
                        CaptureRequest previewRequest = previewRequestBuilder.build();
                        // 设置重复请求，开始录制
                        session.setRepeatingRequest(previewRequest, null, backgroundHandler);
                        // 启动媒体录制器
                        mediaRecorder.start();
                        // 标记为正在录制
                        isRecording = true;

                        upviewHandler.sendEmptyMessage(1);

                       //     recordButton.setText("Stop Recording");
                    } catch (CameraAccessException e) {
                        // 捕获相机访问异常并打印堆栈信息
                        e.printStackTrace();
                    }
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                    // 当会话配置失败时，显示提示信息
                    Toast.makeText(AndroidCameraActivity.this, "Configuration change", Toast.LENGTH_SHORT).show();
                }
            }, backgroundHandler);
        } catch (CameraAccessException | IOException e) {
            // 捕获相机访问异常或 IO 异常并打印堆栈信息
            e.printStackTrace();
        }
    }

    // 设置媒体录制器的方法
    private void setUpMediaRecorder() throws IOException {
        // 创建媒体录制器对象
        mediaRecorder = new MediaRecorder();
        // 设置音频源为麦克风
        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        // 设置视频源为 Surface
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        // 设置输出格式为 MPEG_4
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        // 创建输出文件对象，存储在外部存储的电影目录下
        File outputFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES), "video2.mp4");
        // 设置输出文件的路径
        mediaRecorder.setOutputFile(outputFile.getAbsolutePath());
        Log.e(TAG, "setUpMediaRecorder: OutputFile"+outputFile.getAbsolutePath() );
        // 设置视频编码比特率
        mediaRecorder.setVideoEncodingBitRate(10000000);
        // 设置视频帧率
        mediaRecorder.setVideoFrameRate(30);
        // 设置视频尺寸
        mediaRecorder.setVideoSize(640, 480);
        // 设置视频编码器为 H264
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        // 设置音频编码器为 AAC
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
        // 准备媒体录制器
        mediaRecorder.prepare();
    }

    // 停止录制的方法
    private void stopRecording() {
        if (isRecording) {
            // 标记为停止录制
            isRecording = false;
            // 修改录制按钮的文本为开始录制
            recordButton.setText("Start Recording");
            // 停止媒体录制器
            mediaRecorder.stop();
            // 重置媒体录制器
            mediaRecorder.reset();
            // 创建相机预览
            createCameraPreview();
        }
    }

    // 启动后台线程的方法
    private void startBackgroundThread() {
        // 创建一个名为 CameraBackground 的后台线程
        backgroundThread = new HandlerThread("CameraBackground");
        // 启动后台线程
        backgroundThread.start();
        // 创建一个处理程序，关联到后台线程的消息队列
        backgroundHandler = new Handler(backgroundThread.getLooper());
    }

    // 停止后台线程的方法
    private void stopBackgroundThread() {
        // 安全地退出后台线程
        backgroundThread.quitSafely();
        try {
            // 等待后台线程结束
            backgroundThread.join();
            // 将后台线程对象置为 null
            backgroundThread = null;
            // 将后台处理程序对象置为 null
            backgroundHandler = null;
        } catch (InterruptedException e) {
            // 捕获线程中断异常并打印堆栈信息
            e.printStackTrace();
        }
    }

    // 处理权限请求结果的方法
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == REQUEST_CAMERA_PERMISSION) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
                    && grantResults[1] == PackageManager.PERMISSION_GRANTED
                    && grantResults[2] == PackageManager.PERMISSION_GRANTED) {
                // 如果所有请求的权限都已授予，则打开相机
                openCamera();
            } else {
                // 如果有任何权限被拒绝，显示提示信息
                Toast.makeText(this, "Permissions denied", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private static class UpviewHandler extends Handler {
        // 使用弱引用持有外部类的引用
        private final WeakReference<AndroidCameraActivity> activityWeakReference;

        UpviewHandler(AndroidCameraActivity activity) {
            activityWeakReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            AndroidCameraActivity activity = activityWeakReference.get();
            if (activity != null) {
                // 安全地使用 activity
                ((TextView)activity.findViewById(R.id.recordButton)).setText("Stop Recording");
            }



        }
    }
}